<template>
  <div
    :style="`background: url(${
      theme == 'dark' ? bgDark : bg
    });background-size: 100% 100%;`"
    class="h-full flex justify-center items-center"
    @keyup.enter="login"
  >
    <div
      style="width: 1020px; height: 630px"
      class="rounded-xl flex"
      :class="{ 'bg-white': theme !== 'dark', 'bg-gray-900': theme == 'dark' }"
    >
      <div
        :style="`background: url(${
          theme == 'dark' ? bg1Dark : bg1
        });background-size: 100% 100%;`"
        class="w-1/2"
      >
        <div
          class="mt-20 m-4 font-bold text-4xl text-white text-center italic break-words"
        >
          {{ config.title }}
        </div>
      </div>

      <div class="flex-1 p-20 flex justify-center items-center overflow-hidden">
        <div>
          <div class="text-2xl mb-6">用户登录</div>
          <el-form
            ref="formRef"
            :model="config.data"
            :rules="config.rule"
            label-width="0"
            size="large"
          >
            <el-form-item prop="username">
              <el-input
                v-model="config.data.username"
                placeholder="用户名/手机号码"
              />
            </el-form-item>

            <el-form-item prop="password">
              <el-input
                v-model="config.data.password"
                placeholder="密码"
                type="password"
                show-password
              />
            </el-form-item>

            <div class="flex items-start w-full">
              <el-form-item prop="code" class="flex-1 mr-4">
                <el-input v-model="config.data.code" placeholder="图片验证码" />
              </el-form-item>
              <div class="cursor-pointer" @click="getCodeImage">
                <img :src="codeImage" class="w-28 h-10" />
                <div class="text-right text-sm text-gray-600">
                  看不清?换一张
                </div>
              </div>
            </div>
          </el-form>

          <el-button
            :loading="config.loading"
            type="primary"
            class="w-full mt-4"
            size="large"
            @click="login"
          >
            登录
          </el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue'
import md5 from 'js-md5'

import bg from './image/bg.png'
import bgDark from './image/bg-dark.png'
import bg1 from './image/bg1.png'
import bg1Dark from './image/bg1-dark.png'

const { $http, $api, $store, $storeToRefs, $router, ElMessage } = window
const config = reactive({
  title: process.env.VUE_APP_TITLE,
  loading: false,
  data: {
    username: '',
    password: '',
    code: '',
    grant_type: 'password',
  },
  rule: {
    username: {
      required: true,
      message: '请填写用户名/手机号',
      trigger: 'blur',
    },
    password: { required: true, message: '请填写密码', trigger: 'blur' },
    code: { required: true, message: '请填写验证码', trigger: 'blur' },
  },
})

// theme主题
const { theme } = $storeToRefs($store)

// 密钥
const key = randomNum(24, 16)
function randomNum(len: number, radix: number) {
  const chars =
    '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  const uuid = []
  radix = radix || chars.length

  if (len) {
    // Compact form
    for (let i = 0; i < len; i++) {
      uuid[i] = chars[0 | (Math.random() * radix)]
    }
  } else {
    // rfc4122, version 4 form
    let r

    // rfc4122 requires these characters
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
    uuid[14] = '4'

    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (let i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | (Math.random() * 16)
        uuid[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r]
      }
    }
  }
  return uuid.join('') + new Date().getTime()
}

// 登录
const formRef = ref()
const { account } = $store

async function login() {
  let valid = await formRef.value.validate((valid: boolean) => valid)
  if (!valid) return

  $api.login
    .login(
      {
        ...config.data,
        password: md5(config.data.password),
        key,
      },
      config,
    )
    .then(async (res: any) => {
      account.login(res)

      await getMenu()
      await getUser()

      loginSuccess()
    })
    .catch(() => {
      config.loading = false
      config.data.code = ''
      getCodeImage()
    })
}
function loginSuccess() {
  // 登录成功日志
  $api.login.loginSuccess()

  $router.replace({ path: '/' })
  ElMessage.success('登录成功')
}
onMounted(() => {
  account.logout()
})

// 获取菜单
async function getMenu() {
  let res = await $api.login.getMenu()
  account.setMenu(res)
}

// 获取用户信息
async function getUser() {
  let res = await $api.login.getUser()
  account.setUser(res)
}

// 图片验证码
const codeImage = ref('')
let codeTimer: ReturnType<typeof setTimeout>
function getCodeImage() {
  $http({
    url: 'login.getCodeImage',
    params: { key },
    responseType: 'arraybuffer',
    headers: {
      Authorization: true,
    },
  }).then((res: ArrayBuffer) => {
    codeImage.value =
      'data:image/png;base64,' +
      btoa(
        new Uint8Array(res).reduce(
          (data, byte) => data + String.fromCharCode(byte),
          '',
        ),
      )
  })
}
onMounted(() => {
  getCodeImage()
  codeTimer = setInterval(() => getCodeImage(), 30 * 1000)
})
onUnmounted(() => {
  codeTimer && clearInterval(codeTimer)
})
</script>

<style lang="scss" scoped>
:deep(.el-form) {
  .el-input__wrapper {
    padding: 1px;
  }

  .el-input__inner {
    padding: 0 16px;
    border-radius: 4px;
  }

  .el-input__icon {
    margin: 0 4px;
  }

  .el-input-group__prepend {
    padding: 0;
  }
}
</style>
